package com.wanwu.channel.remote.alipay.util;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.wanwu.channel.common.enums.ExceptionEnum;
import com.wanwu.channel.common.exception.SystemException;
import com.wanwu.channel.remote.alipay.config.AlipayConfiguration;
import com.wanwu.channel.remote.alipay.httpclient.HttpProtocolHandler;
import com.wanwu.channel.remote.alipay.httpclient.HttpRequest;
import com.wanwu.channel.remote.alipay.httpclient.HttpResponse;
import com.wanwu.channel.remote.alipay.httpclient.HttpResultType;
import com.wanwu.channel.remote.alipay.sign.RSA;
import org.apache.commons.httpclient.NameValuePair;

/* *
 *类名：AlipaySubmit
 *功能：支付宝各接口请求提交类
 *详细：构造支付宝各接口表单HTML文本，获取远程HTTP数据
 *版本：3.3
 *日期：2012-08-13
 *说明：
 *以下代码只是为了方便商户测试而提供的样例代码，商户可以根据自己网站的需要，按照技术文档编写,并非一定要使用该代码。
 *该代码仅供学习和研究支付宝接口使用，只是提供一个参考。
 */

public class AlipaySubmit {

    /**
     * 支付宝提供给商户的服务接入网关URL(新)
     */
    private static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";

    /**
     * 生成签名结果
     * @param sPara 要签名的数组
     * @param qdDecPriKey 趣店私钥
     * @return 签名结果字符串
     */
    public static String buildRequestMysign(Map<String, String> sPara, String qdDecPriKey) {
        String prestr = AlipayCore.createLinkString(sPara); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String mysign = "";
        if(AlipayConfiguration.getInstance().getDeclareSignType().equals("RSA") ){
            mysign = RSA.sign(prestr, qdDecPriKey, AlipayConfiguration.getInstance().getInputCharset());
        }
        return mysign;
    }

    /**
     * 生成要请求给支付宝的参数数组
     * @param sParaTemp 请求前的参数数组
     * @param qdDecPriKey 趣店私钥
     * @return 要请求的参数数组
     */
    private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp, String qdDecPriKey) {
        //除去数组中的空值和签名参数
        Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
        //生成签名结果
        String mysign = buildRequestMysign(sPara, qdDecPriKey);

        //签名结果与签名方式加入请求提交参数组中
        sPara.put("sign", mysign);
        sPara.put("sign_type", AlipayConfiguration.getInstance().getDeclareSignType());

        return sPara;
    }



    public static String buildRequest(Map<String, String> sParaTemp, String openApiDomain, String signType,
                                      String privateKey, String inputCharset){
        //待请求参数数组
        Map<String, String> sPara = buildRequestPara(sParaTemp, signType, privateKey, inputCharset);

        HttpProtocolHandler httpProtocolHandler = HttpProtocolHandler.getInstance();

        HttpRequest request = new HttpRequest(HttpResultType.BYTES);
        //设置编码集
        request.setCharset(inputCharset);

        request.setParameters(generatNameValuePair(sPara));
        request.setUrl(openApiDomain + "_input_charset=" + inputCharset);
        String strResult = null;
        try {
            HttpResponse response = httpProtocolHandler.execute(request, "", "");

            strResult = response.getStringResult();
        }catch (Exception e){
            throw new SystemException(ExceptionEnum.E10022);
        }
        return strResult;

    }

    /**
     * 生成要请求给支付宝的参数数组
     *
     * @param sParaTemp 请求前的参数数组
     * @return 要请求的参数数组
     */
    private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp, String signType, String privateKey, String inputCharset) {
        //除去数组中的空值和签名参数
        Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
        //生成签名结果
        String mysign = buildRequestMysign(sPara, signType, privateKey, inputCharset);

        //签名结果与签名方式加入请求提交参数组中
        sPara.put("sign", mysign);
        sPara.put("sign_type", signType);

        return sPara;
    }

    /**
     * 生成签名结果
     *
     * @param sPara 要签名的数组
     * @return 签名结果字符串
     */
    public static String buildRequestMysign(Map<String, String> sPara, String signType, String privateKey, String inputCharset) {
        String prestr = AlipayCore.createLinkString(sPara); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String mysign = "";
        if (signType.equals("RSA")) {
            mysign = com.wanwu.channel.common.util.RSA.sign(prestr, privateKey, inputCharset);
        }
        return mysign;
    }


    /**
     * 建立请求，以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
     * 如果接口中没有上传文件参数，那么strParaFileName与strFilePath设置为空值
     * 如：buildRequest("", "",sParaTemp)
     * @param strParaFileName 文件类型的参数名
     * @param strFilePath 文件路径
     * @param sParaTemp 请求参数数组
     * @param qdDecPriKey 趣店请求支付宝报关的私钥
     * @return 支付宝处理结果
     * @throws Exception
     */
    public static String buildRequest(String strParaFileName, String strFilePath,Map<String, String> sParaTemp, String qdDecPriKey) throws Exception {
        //待请求参数数组
        Map<String, String> sPara = buildRequestPara(sParaTemp, qdDecPriKey);

        HttpProtocolHandler httpProtocolHandler = HttpProtocolHandler.getInstance();

        HttpRequest request = new HttpRequest(HttpResultType.BYTES);
        //设置编码集
        request.setCharset(AlipayConfiguration.getInstance().getInputCharset());

        request.setParameters(generatNameValuePair(sPara));
        request.setUrl(ALIPAY_GATEWAY_NEW+"_input_charset="+AlipayConfiguration.getInstance().getInputCharset());

        HttpResponse response = httpProtocolHandler.execute(request,strParaFileName,strFilePath);

        String strResult = response.getStringResult();

        return strResult;
    }

    public static String postRequest(Map<String, String> sParaTemp, String qdDecPriKey) throws Exception {
        return buildRequest("","",sParaTemp,qdDecPriKey);
    }


        /**
         * MAP类型数组转换成NameValuePair类型
         * @param properties  MAP类型数组
         * @return NameValuePair类型数组
         */
    private static NameValuePair[] generatNameValuePair(Map<String, String> properties) {
        NameValuePair[] nameValuePair = new NameValuePair[properties.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            nameValuePair[i++] = new NameValuePair(entry.getKey(), entry.getValue());
        }

        return nameValuePair;
    }

}
